/**
 * @author Angel Marcos Sosa León.
 */

package uoc.ei.practica;
import uoc.ei.tads.ListaEncadenada;
import uoc.ei.tads.Iterador;


public class ScrabbleManagerImpl implements ScrabbleManager {
	/** 
	 * lista de campeonatos del Scrabble
	 */
	private ListaEncadenada<ChampionShip> campeonatos;
	/** 
	 * lista de campeonatos
	 */
	/**
	 * Constructor clase ScrabbleManagerImpl. Inicializa las estructuras de datos
	 */
	public ScrabbleManagerImpl() {
		this.campeonatos=new ListaEncadenada<ChampionShip>();
	}
	
	/**
	   * Añade un campeonato con el Id indicado 
	   * @param IdChamp  identificador único de Campeonato 
	   * @throws  EIException si el campeonato ya existe.
	   */
	@Override
	public void addChampionShip(String championShipId) throws EIException {
		ChampionShip newChamp = new ChampionShip(championShipId);
		
		ChampionShip champ = findChampionShip(championShipId);
		if(champ==null)
			campeonatos.insertarAlFinal(newChamp);		
		else
		throw new EIException(Messages.CHAMPIONSHIP_ALREADY_EXISTS);
		
	}
	 /**
	   * Devuelve un iterador con todas los campeonatos
	   * En el caso que no haya campeonatos,
	   * se muestra el mensaje "No hay campeonatos"
	   * @return  iterador con los campeonatos
	   * @throws EIException (No hay campeonatos)
	   */
	@Override
	public Iterador<ChampionShip> championShips() throws EIException {
		if (campeonatos.estaVacio())
		{		
		throw new EIException(Messages.NO_CHAMPIONSHIPS);
		}
		else return  campeonatos.elementos();
	}
	
	/**
	   * Devuelve los campeonatos identificada por idChamp
	   * Utiliza un iterador para recorrer la lista de Campeonatos y 
	   * compararlos 
	   * @param IdChamp  identificador único de Campeonato 
	   * @return  el campeonato encontrada; si no existe, devuelve null
	   */
	
	private ChampionShip findChampionShip(String idChamp) {
		ChampionShip c = null;
		boolean found = false;
		Iterador<ChampionShip> it = campeonatos.elementos();
		while(it.haySiguiente()==true && found==false)
		{
			c=it.siguiente();
			if(c.getId().equals(idChamp))
			{
				found = true;	
				
			}
		}
			
		return  found ? c : null;
	      
  }
	/**
	   * Metodo que añade una palabra al diccionario de palabras de un campeonato
	   * @param championShipId  identificador único de Campeonato, Word palabra a añadir
	   * @throws EIException Si No existe el campeonato o la palabra ya ha sido insertada
	   */
	
	@Override
	public void addWord(String championShipId, String word) throws EIException 
	{
		if(findChampionShip(championShipId)!=null)
		{
			ChampionShip champ = findChampionShip(championShipId);
			if(champ.findWords(word)==null)
			{	
				Word palabra = new Word(championShipId, word);
				champ.addWord(palabra);
			} else throw new EIException(Messages.WORD_ALREADY_EXISTS);
		} else throw new EIException(Messages.CHAMPIONSHIP_NOT_FOUND);
		
	}
		
	
	/**
	   * Devuelve un iterador con todas las palabras de un campeonato en concreto
	   * @param   championShipId Ide del campeonato,
	   * @return  iterador con los palabras
	   * @throws EIException No se ha encontrado el campeonato o no hay letras.
	   */
	
	@Override
	public Iterador<Word> words(String championShipId) throws EIException 
	{
		
		if(findChampionShip(championShipId)!=null)
		{			
			ChampionShip champ = findChampionShip(championShipId);
		    return champ.words(); 
		}
		
		else throw new EIException(Messages.CHAMPIONSHIP_NOT_FOUND);		    
	    	
	}
	
	/**
	   * Metodo que añade una letra a un campeonato.
	   * @param championShipId  identificador único de Campeonato, letter letra a añadir
	   * @throws EIException Si No existe el campeonato,la letra ya ha sido insertada,
	   *  o se ha llegado al limite de letras
	   */
	

	@Override
	public void addLetter(String championShipId, String letter, int points,
			int total) throws EIException {
		if(findChampionShip(championShipId)!=null)
		{		
			ChampionShip champ = findChampionShip(championShipId);
				if(champ.findLetters(letter)!=null)
				{
					throw new EIException(Messages.LETTER_ALREADY_EXISTS);
					/*
					Letter l =champ.findLetters(letter);
					l.setNumFichas(total);
					l.setPuntos(points);*/
				}
				else
				{
						
					    if (champ.getNumLetras()<ScrabbleManager.MAX_LETTERS-1)
					    {
					    	Letter letra = new Letter(championShipId, letter, points, total);
					    	champ.addLetter(letra);
					    }
				else throw new EIException(Messages.MAX_LETTERS);
				}			
		}			
		else throw new EIException(Messages.CHAMPIONSHIP_NOT_FOUND);		
	}
	
	/**
	   * Devuelve un iterador con todas las letras de un campeonato en concreto
	   * @param   championShipId Ide del campeonato,
	   * @return  iterador con los letras
	   * @throws EIException No se ha encontrado el campeonato o no hay letras.
	   */
	
	@Override
	public Iterador<Letter> letters(String championShipId) throws EIException {
		if(findChampionShip(championShipId)!=null)
		{			
			ChampionShip champ = findChampionShip(championShipId);
			if (champ.getNumLetras()==0) throw new EIException(Messages.NO_LETTERS);
		    return champ.letras(); 
		}
		
		else throw new EIException(Messages.CHAMPIONSHIP_NOT_FOUND);	
	}

	/**
	   * Metodo que añade una partida a un campeonato.
	   * @param championShipId  identificador único de Campeonato, gameId identificador de partida
	   *  player 1 primer jugador,player 2 segundo jugador
	   * @throws EIException Si No existe el campeonato o si la partida ya existe
	   */
	@Override
	public void addGame(String championShipId, String gameId, String player1,
			String player2) throws EIException {
		if(findChampionShip(championShipId)!=null)
		{ 
			ChampionShip champ = findChampionShip(championShipId);
			if(champ.findGames(gameId)==null)
			{
				Game partida = new Game(championShipId, gameId, player1, player2);
				champ.addGame(partida);	
			}						
			else throw new EIException(Messages.GAME_ALREADY_EXISTS);
		}
		else throw new EIException(Messages.CHAMPIONSHIP_NOT_FOUND);
		
	}
	
	/**
	   * Devuelve un iterador con todas las partidas de un campeonato
	   * @param   championShipId Id del campeonato,
	   * @return  iterador con las partidas
	   * @throws EIException No se ha encontrado el campeonato
	   */
	
	@Override
	public Iterador<Game> games(String championShipId) throws EIException {
		if(findChampionShip(championShipId)!=null)
		{			
			ChampionShip champ = findChampionShip(championShipId);
		    return champ.games(); 
		}
		
		else throw new EIException(Messages.CHAMPIONSHIP_NOT_FOUND);
	}

	/**
	   * Metodo que añade una ficha a una partida de  un campeonato.
	   * @param championShipId  identificador único de Campeonato, gameId identificador de partida
	   *  letter letra a añadir
	   * @throws EIException Si No existe el campeonato,si no existe la partida,si la partida esta empezada 
	   * si la letra no existe o si se ha superado el maximo de letras
	   * 
	   */
	@Override
	public void addCard(String championShipId, String gameId, String letter)
			throws EIException {
		if(findChampionShip(championShipId)!=null)
		{			
			ChampionShip champ = findChampionShip(championShipId);
			if(champ.findGames(gameId)!=null)
			{
				Game g = champ.findGames(gameId);
				if(g.isStart()==false)
				{
					if(champ.findLetters(letter)!=null)
					{
						Letter l = champ.findLetters(letter);
						if (l.getNumFichas()>g.numfichasLetra(letter))
						{
							Card ficha = new Card(championShipId, gameId, letter);
							g.addCard(ficha);
						}else throw new EIException(Messages.MAX_LETTERS);
					}else throw new EIException(Messages.LETTER_NOT_FOUND);
				}else throw new EIException(Messages.GAME_ALREADY_OPEN);
			}else throw new EIException(Messages.GAME_NOT_FOUND);			
		}else throw new EIException(Messages.CHAMPIONSHIP_NOT_FOUND);		
	}
	
	/**
	   * Metodo da por comenzada la partida y reparte fichas entre jugadores
	   * @param championShipId  identificador único de Campeonato, gameId identificador de partida
	   * @throws EIException Si No existe el campeonato o si no existe la partida
	   **/

	@Override
	public void startGame(String championShipId, String gameId)
			throws EIException {
		if(findChampionShip(championShipId)!=null)
		{			
			ChampionShip champ = findChampionShip(championShipId);
			if(champ.findGames(gameId)!=null)
			{
				Game g = champ.findGames(gameId);
				g.startGame();
				
			}else throw new EIException(Messages.GAME_NOT_FOUND);
			
		}else throw new EIException(Messages.CHAMPIONSHIP_NOT_FOUND);
		
	}
	 
	/**
	   * Devuelve un iterador con todas las fichas de una partida y campeonato en concreto asociadas a un jugador
	   * @param   championShipId Ide del campeonato,gameId Id de la partida,playerId Id del jugador
	   * @return  iterador con los fichas
	   * @throws EIException No se ha encontrado el campeonato,no se ha encontrado la partida,no hay fichas asignadas a
	   * ese jugador
	   */
	@Override
	public Iterador<Card> cards(String championShipId, String gameId,
			String playerId) throws EIException
	{
		if(findChampionShip(championShipId)!=null)
			{			
				ChampionShip champ = findChampionShip(championShipId);	
				if(champ.findGames(gameId)!=null)
				{
					Game g = champ.findGames(gameId);
					if(g.p1Orp2(playerId)!=0)
					{
					  return g.fichasJugadorMod(g.p1Orp2(playerId));
					  
					}else throw new EIException(Messages.NO_CARDS);						
				}else throw new EIException(Messages.GAME_NOT_FOUND);	
			}else throw new EIException(Messages.CHAMPIONSHIP_NOT_FOUND);	
	}
	
	 /**
	   * Devuelve un iterador con todas las fichas de una partida y campeonato en concreto
	   * @param   championShipId Ide del campeonato,gameId Id de la partida
	   * @return  iterador con los fichas
	   * @throws EIException No se ha encontrado el campeonato o no se ha encontrado la partida
	   */
	
	@Override
	public Iterador<Card> cardsGame(String championShipId, String gameId)
			throws EIException 
		{
			if(findChampionShip(championShipId)!=null)
				{			
					ChampionShip champ = findChampionShip(championShipId);	
					if(champ.findGames(gameId)!=null)
					{
						Game g = champ.findGames(gameId);
						return g.fichas();
					}else throw new EIException(Messages.GAME_NOT_FOUND);	
				}else throw new EIException(Messages.CHAMPIONSHIP_NOT_FOUND);	
		}
	

}
